package com.woniuxy.enjoylife.advice;

import com.woniuxy.enjoylife.entity.Log;
import com.woniuxy.enjoylife.entity.Role;
import com.woniuxy.enjoylife.mapper.LogMapper;
import com.woniuxy.enjoylife.mapper.UserMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.Map;


@Component
@Aspect
public class LogAdvice {
    @Resource
    private HttpServletRequest request;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private UserMapper userMapper;

    @Resource
    private LogMapper logMapper;


    @Pointcut("execution(* com.woniuxy.enjoylife.controller.*.*(..))&&!execution(* com.woniuxy.enjoylife.controller.AliPayController.*(..))&&!execution(* com.woniuxy.enjoylife.controller.FileController.*(..))&&!execution(* com.woniuxy.enjoylife.controller.UserController.login(..))&&!execution(* com.woniuxy.enjoylife.controller.UserController.findByAccount(..))&&!execution(* com.woniuxy.enjoylife.controller.UserController.register(..))&&!execution(* com.woniuxy.enjoylife.controller.UserController.findByEmail(..))&&!execution(* com.woniuxy.enjoylife.controller.UserController.sendCode(..))&&!execution(* com.woniuxy.enjoylife.controller.UserController.loguot(..))")
    public void pc() {
    }


    //环绕通知，将数据缓存到redis，redis中无数据再进行查询
    @Around("pc()")
    public Object around(ProceedingJoinPoint joinPoint) {
        Object proceed = null;
        try {


//            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//            HttpServletRequest request = attributes.getRequest();


//            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//            MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
//            MultipartHttpServletRequest multipartRequest = resolver.resolveMultipart(request);
//            int i = (int)multipartRequest.getSession().getAttribute("id");


//            int i = (int) request.getSession().getAttribute("id");


            String token = null;
            int i = 0;

            try {
                if (!request.getRequestURI().contains("file")) {
                    token = request.getHeader("token");
                    i = (int) redisTemplate.opsForValue().get(token);
                }
            } catch (IllegalArgumentException e) {
                System.out.println("redis无数据");
            } catch (NullPointerException e){
                System.out.println("请求无header");
            }

//            int i = 2;
//            System.out.println(i);
            if (i != 0) {
                List<Role> roleList = userMapper.selectUserRole(i);
                String userRoles = roleList.toString();
                if (null != userRoles && userRoles.length() != 0) {
                    if (userRoles.contains("平台")) {
                        Object target = joinPoint.getTarget();

                        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
                        //获取参数名的数组
                        String[] parameterNames = signature.getParameterNames();
                        //获取原方法传入的参数值
                        Object[] args = joinPoint.getArgs();

                        StringBuilder sb = new StringBuilder();

                        for (int j = 0; j < parameterNames.length; j++) {
                            sb.append(parameterNames[j] + ":");
                            sb.append(args[j].toString());
                            sb.append(",");
                        }
                        //请求url
                        StringBuffer requestURL = request.getRequestURL();
                        request.getServerPort();

                        String uri = request.getRequestURI();//返回请求行中的资源名称
                        String url = request.getRequestURL().toString();//获得客户端发送请求的完整url
                        String ip = request.getRemoteAddr();//返回发出请求的IP地址
                        String params = request.getQueryString();//返回请求行中的参数部分
                        String host = request.getRemoteHost();//返回发出请求的客户机的主机名
                        int port = request.getRemotePort();//返回发出请求的客户机的端口号。

                        String requestInfo = "uri:" + uri + ",url:" + url + ",ip:" + ip + ",请求行参数：" + params + ",客户端名称:" + host + ",客户端端口：" + port;

                        String targetToString = target.toString().toLowerCase();
                        String LogTarget = "用户";
                        if (targetToString.contains("comment")) {
                            LogTarget = "评论";
                        } else if (targetToString.contains("order")) {
                            LogTarget = "订单";
                        } else if (targetToString.contains("goods")) {
                            LogTarget = "商品";
                        } else if (targetToString.contains("activity")) {
                            LogTarget = "活动";
                        } else if (targetToString.contains("house") || targetToString.contains("community")) {
                            LogTarget = "房屋";
                        } else if (targetToString.contains("recent")) {
                            LogTarget = "动态";
                        } else if (targetToString.contains("server")) {
                            LogTarget = "服务";
                        } else if (targetToString.contains("suggest")) {
                            LogTarget = "投诉";
                        } else if (targetToString.contains("user")) {
                            LogTarget = "用户";
                        }


                        String LogType = "查";
                        String typeToString = signature.getName().toLowerCase();
                        if (typeToString.contains("add") || typeToString.contains("insert") || typeToString.contains("save")) {
                            LogType = "增";
                        } else if (typeToString.contains("del")) {
                            LogType = "删";
                        } else if (typeToString.contains("update") || typeToString.contains("cancle") || typeToString.contains("cancel") || typeToString.contains("change")) {
                            LogType = "改";
                        } else if (typeToString.contains("select") || typeToString.contains("find") || typeToString.contains("get") || typeToString.contains("page") || typeToString.contains("all")) {
                            LogType = "查";
                        }

                        Log log = new Log();
                        log.setUid(i);
                        log.setTarget(LogTarget);
                        log.setType(LogType);
                        log.setTime(LocalDateTime.now());
                        log.setContent("---调用类：" + target.toString() + ",调用方法：" + signature.getName() + ",传入参数：" + new String(sb) + "---请求信息---" + requestInfo);

                        redisTemplate.opsForList().rightPush("logList", log);
//                    logMapper.insertLog(log);
                    }
                }

            }
            proceed = joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            try {
                proceed = joinPoint.proceed();
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }

        return proceed;
    }

}